package com.tianji.learning.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tianji.api.cache.CategoryCache;
import com.tianji.api.client.course.CatalogueClient;
import com.tianji.api.client.course.CourseClient;
import com.tianji.api.client.search.SearchClient;
import com.tianji.api.client.user.UserClient;
import com.tianji.api.dto.course.CataSimpleInfoDTO;
import com.tianji.api.dto.course.CourseFullInfoDTO;
import com.tianji.api.dto.course.CourseSimpleInfoDTO;
import com.tianji.api.dto.user.UserDTO;
import com.tianji.common.domain.dto.PageDTO;
import com.tianji.common.exceptions.BadRequestException;
import com.tianji.common.utils.BeanUtils;
import com.tianji.common.utils.CollUtils;
import com.tianji.common.utils.UserContext;
import com.tianji.learning.domian.DTO.QuestionFormDTO;
import com.tianji.learning.domian.query.QuestionAdminPageQuery;
import com.tianji.learning.domian.query.QuestionPageQuery;
import com.tianji.learning.domian.vo.QuestionAdminVO;
import com.tianji.learning.domian.vo.QuestionVO;
import com.tianji.learning.entity.InteractionQuestion;
import com.tianji.learning.entity.InteractionReply;
import com.tianji.learning.enums.QuestionStatus;
import com.tianji.learning.mapper.InteractionQuestionMapper;
import com.tianji.learning.mapper.InteractionReplyMapper;
import com.tianji.learning.service.IInteractionQuestionService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * <p>
 * 互动提问的问题表 服务实现类
 * </p>
 *
 * @author author
 * @since 2024-03-21
 */
@Service
@RequiredArgsConstructor
public class InteractionQuestionServiceImpl extends ServiceImpl<InteractionQuestionMapper, InteractionQuestion> implements IInteractionQuestionService {

    private final InteractionReplyMapper replyMapper;

    private final UserClient userClient;

    private final SearchClient searchClient;

    private final CourseClient courseClient;

    private final CatalogueClient catalogueClient;

    private final CategoryCache categoryCache;

    @Override
    @Transactional
    public void createQuestion(QuestionFormDTO questionFormDTO) {
        //1.获取登录用户信息
        Long userId = UserContext.getUser();
        //2.数据转换
        InteractionQuestion question = BeanUtils.copyBean(questionFormDTO, InteractionQuestion.class);
        //3.设置用户id
        question.setUserId(userId);
        //4.保存
        save(question);
    }

    /**
     *根据ID删除互动问题
     */
    @Override
    @Transactional
    public void deleteById(Long id) {
        // 1.获取当前登录用户
        Long userId = UserContext.getUser();
        // 2.查询当前问题
        InteractionQuestion q = getById(id);
        if (q == null) {
            return;
        }
        // 3.判断是否是当前用户的问题
        if (!q.getUserId().equals(userId)) {
            // 不是，抛出异常
            throw new BadRequestException("无权删除他人的问题");
        }
        // 4.删除问题
        removeById(id);
        // 5.删除回答
        replyMapper.delete(
                new QueryWrapper<InteractionReply>().lambda().eq(InteractionReply::getQuestionId, id)
        );
    }
    /**
     * 根据ID修改互动问题
     */
    @Override
    public void updateQuestion(Long id, QuestionFormDTO questionDTO) {
        // 1.获取当前登录用户
        Long userId = UserContext.getUser();
        // 2.查询当前问题
        InteractionQuestion q = getById(id);
        if (q == null) {
            throw new BadRequestException("问题不存在");
        }
        // 3.判断是否是当前用户的问题
        if (!q.getUserId().equals(userId)) {
            // 不是，抛出异常
            throw new BadRequestException("无权修改他人的问题");
        }
        // 4.修改问题
        InteractionQuestion question = BeanUtils.toBean(questionDTO, InteractionQuestion.class);
        question.setId(id);
        updateById(question);
    }

    @Override
    public PageDTO<QuestionVO> queryQuestionPage(QuestionPageQuery pageQuery) {
        //1、参数校验：课程ID和小节ID不能同时为空
        Long courseId = pageQuery.getCourseId();
        Long sectionId = pageQuery.getSectionId();
        if (ObjectUtil.isEmpty(courseId) && ObjectUtil.isEmpty(sectionId)) {
            throw new BadRequestException("课程ID和小节ID不能同时为空！");
        }

        //2、分页查询
        // select * from interaction_question where courseId = ? and sectionId = ? and user_id = ? and hidden = 0
        // order by create_time desc limit 0,10
        Page<InteractionQuestion> page = lambdaQuery()
                .select(InteractionQuestion.class, column -> !column.getProperty().equals("description"))  //除了描述，其他字段都需要查询出来
                .eq(ObjectUtil.isNotEmpty(courseId), InteractionQuestion::getCourseId, courseId)
                .eq(ObjectUtil.isNotEmpty(sectionId), InteractionQuestion::getSectionId, sectionId)
                .eq(pageQuery.getOnlyMine(), InteractionQuestion::getUserId, UserContext.getUser())
                .eq(InteractionQuestion::getHidden, false)
                .page(pageQuery.toMpPageDefaultSortByCreateTimeDesc());

        List<InteractionQuestion> records = page.getRecords();
        if (ObjectUtil.isEmpty(records)) {
            return PageDTO.empty(page);
        }

        //3、根据用户ID查询提问者信息，根据最近一次回答ID查询最近一次回答信息
        //3.1、从问题的分页结果中收集提问者ID集合、最近一次回答ID集合
        Set<Long> userIds = new HashSet<>();
        Set<Long> answerIds = new HashSet<>();
        for (InteractionQuestion record : records) {
            answerIds.add(record.getLatestAnswerId());
            //如果是提问者是非匿名，才参与查询
            if (!record.getAnonymity()) {
                userIds.add(record.getUserId());
            }
        }

        //3.2、根据最近一次回答ID集合进行查询 -> 转成Map（最近依次回答ID：回复信息本身）
        Map<Long, InteractionReply> replyMap = new HashMap<>(answerIds.size());
        if (ObjectUtil.isNotEmpty(answerIds)) {
            List<InteractionReply> replies = replyMapper.selectBatchIds(answerIds);
            //replyMap = replies.stream().collect(Collectors.toMap(a -> a.getId(), Function.identity()));
            for (InteractionReply reply : replies) {
                replyMap.put(reply.getId(), reply);
                if (!reply.getAnonymity()) {
                    userIds.add(reply.getUserId());
                }
            }
        }

        //3.3、根据用户ID集合进行查询 -> 转成Map（用户ID：用户对象本身）
        Map<Long, UserDTO> userMap = new HashMap<>(userIds.size());
        if (ObjectUtil.isNotEmpty(userIds)) {
            List<UserDTO> users = userClient.queryUserByIds(userIds);
            userMap = users.stream().collect(Collectors.toMap(u -> u.getId(), Function.identity()));
        }

        //4、封装VO
        List<QuestionVO> voList = new ArrayList<>(records.size());
        for (InteractionQuestion record : records) {
            //4.1、拷贝属性
            QuestionVO vo = BeanUtils.copyBean(record, QuestionVO.class);

            //4.2、封装提问者信息（提问者昵称、提问者头像）
            if (!record.getAnonymity()) {
                UserDTO userDTO = userMap.get(vo.getUserId());
                if (ObjectUtil.isNotEmpty(userDTO)) {
                    vo.setUserName(userDTO.getName());
                    vo.setUserIcon(userDTO.getIcon());
                }
            }

            //4.3、封装最近一次回答信息（近一次回答者昵称、最近一次回答内容）
            InteractionReply reply = replyMap.get(record.getLatestAnswerId());
            if (ObjectUtil.isNotEmpty(reply)) {
                vo.setLatestReplyContent(reply.getContent());
                if (!reply.getAnonymity()) {
                    UserDTO userDTO = userMap.get(reply.getUserId());
                    if (ObjectUtil.isNotEmpty(userDTO)) {
                        vo.setLatestReplyUser(userDTO.getName());
                    }
                }
            }

            //4.4、将vo添加至volist
            voList.add(vo);
        }

        return PageDTO.of(page, voList);
    }

    @Override
    public QuestionVO queryQuestionById(Long id) {
        //1.根据id查询数据
        InteractionQuestion question = getById(id);
        //2.数据校验
        if (ObjectUtil.isEmpty(question) || question.getHidden()){
            // 没有数据或者是被隐藏了
            return null;
        }
        //3.查询提问者信息
        UserDTO userDTO = null;
        if (!question.getAnonymity()){
            userDTO = userClient.queryUserById(question.getUserId());
        }
        //4.封装vo
        QuestionVO vo = BeanUtils.copyBean(question, QuestionVO.class);
        if (ObjectUtil.isNotEmpty(userDTO)){
            vo.setUserName(userDTO.getName());
            vo.setUserIcon(userDTO.getIcon());
        };
        //5.返回结果
        return vo;
    }

    @Override
    public PageDTO<QuestionAdminVO> queryQuestionPageAdmin(QuestionAdminPageQuery pageQuery) {
        //1.处理课程名称，得到课程id
        List<Long> courseIds = null;
        if (ObjectUtil.isNotEmpty(pageQuery.getCourseName())){
            courseIds = searchClient.queryCoursesIdByName(pageQuery.getCourseName());
            if (CollUtils.isEmpty(courseIds)){
                return PageDTO.empty(0L,0L);
            }
        }
        //2.分页查询
        Integer status = pageQuery.getStatus();
        LocalDateTime begin = pageQuery.getBeginTime();
        LocalDateTime end = pageQuery.getEndTime();
        Page<InteractionQuestion> page = lambdaQuery()
                .in(ObjectUtil.isNotEmpty(courseIds), InteractionQuestion::getCourseId, courseIds)
                .eq(ObjectUtil.isNotEmpty(status), InteractionQuestion::getStatus, status)
                .gt(ObjectUtil.isNotEmpty(begin), InteractionQuestion::getCreateTime, begin)
                .lt(ObjectUtil.isNotEmpty(end), InteractionQuestion::getCreateTime, end)
                .page(pageQuery.toMpPageDefaultSortByCreateTimeDesc());
        List<InteractionQuestion> records = page.getRecords();
        if (ObjectUtil.isEmpty(records)){
            return PageDTO.empty(page);
        }

        //3.准备VO需要的数据： 用户数据、课程数据、章节数据 （补充缺少的数据）
        Set<Long> userIds = new HashSet<>();
        Set<Long> cIds = new HashSet<>();
        Set<Long> cataIds = new HashSet<>();
        //3.1.获取各种数据的id 集合
        for (InteractionQuestion q : records) {
            userIds.add(q.getUserId());
            cIds.add(q.getCourseId());
            cataIds.add(q.getChapterId());
            cataIds.add(q.getSectionId());
        }
          //3.2.根据id查询用户
        List<UserDTO> users = userClient.queryUserByIds(userIds);
        Map<Long, UserDTO> userMap = new HashMap<>(users.size());
        if (CollUtils.isNotEmpty(users)){
            userMap = users.stream().collect(Collectors.toMap(UserDTO::getId,u -> u));
        }

        //3.3.根据id 查询课程
        List<CourseSimpleInfoDTO> cInfos = courseClient.getSimpleInfoList(cIds);
        Map<Long, CourseSimpleInfoDTO> cInfosMap = new HashMap<>(cInfos.size());
        if (CollUtils.isNotEmpty(cInfos)){
            cInfosMap = cInfos.stream().collect(Collectors.toMap(CourseSimpleInfoDTO::getId,c -> c));
        }
        //3.4.根据id 查询章节
        List<CataSimpleInfoDTO> catas = catalogueClient.batchQueryCatalogue(cataIds);
        Map<Long, String> cataMap = new HashMap<>(catas.size());
        if (CollUtils.isNotEmpty(catas)) {
            cataMap = catas.stream()
                    .collect(Collectors.toMap(CataSimpleInfoDTO::getId, CataSimpleInfoDTO::getName));
        }
        //4.封装VO
        List<QuestionAdminVO> voList = new ArrayList<>(records.size());
        //4.1.将po 转换成vo ， 属性copy
        for (InteractionQuestion q : records) {
            QuestionAdminVO vo = BeanUtils.copyBean(q, QuestionAdminVO.class);
            voList.add(vo);
            //4.2.用户信息
            UserDTO user = userMap.get(q.getUserId());
            if (ObjectUtil.isNotEmpty(user)){
                vo.setUserName(user.getName());
            }
            //4.3.课程信息以及分类信息
            CourseSimpleInfoDTO cInfo = cInfosMap.get(q.getCourseId());
            if (ObjectUtil.isNotEmpty(cInfo)){
                vo.setCourseName(cInfo.getName());
                vo.setCategoryName(categoryCache.getCategoryNames(cInfo.getCategoryIds()));
            }
            //4.4章节信息
            vo.setChapterName(cataMap.getOrDefault(q.getChapterId(),""));
            vo.setSectionName(cataMap.getOrDefault(q.getSectionId(),""));
        }


        //5.返回结果
        return PageDTO.of(page, voList);
    }

    @Override
    public QuestionAdminVO queryQuestionByIdAdmin(Long id) {
        //1.根据id查询数据
        InteractionQuestion question = getById(id);
        //2.数据校验
        if (ObjectUtil.isEmpty(question)){
            // 没有数据或者是被隐藏了
            return null;
        }
        //3.将po转换为vo
        QuestionAdminVO vo = BeanUtils.copyBean(question, QuestionAdminVO.class);
        //4.查询提问者信息
        UserDTO userDTO = userClient.queryUserById(question.getUserId());
        if (ObjectUtil.isNotEmpty(userDTO)){
            vo.setUserName(userDTO.getName());
            vo.setUserIcon(userDTO.getIcon());
        }
        //5.查询课程信息
        CourseFullInfoDTO cInfo = courseClient.getCourseInfoById(question.getCourseId(), false, true);
        if (ObjectUtil.isNotEmpty(cInfo)){
            //5.1.课程名称
            vo.setCourseName(cInfo.getName());
            //5.2.分类信息
            vo.setCategoryName(categoryCache.getCategoryNames(cInfo.getCategoryIds()));
            //5.3.教师信息
            List<Long> teacherIds = cInfo.getTeacherIds();
            List<UserDTO> teachers = userClient.queryUserByIds(teacherIds);
            if (CollUtils.isNotEmpty(teachers)){
            vo.setTeacherName(teachers.stream()
                    .map(UserDTO::getName).collect(Collectors.joining(",")));
            }
        }
        //6.查询章信息
        List<CataSimpleInfoDTO> catas = catalogueClient.batchQueryCatalogue(
                List.of(question.getChapterId(), question.getSectionId()));
        Map<Long, String> cataMap = new HashMap<>(catas.size());
        if (CollUtils.isNotEmpty(catas)) {
            cataMap = catas.stream()
                    .collect(Collectors.toMap(CataSimpleInfoDTO::getId, CataSimpleInfoDTO::getName));
        }
        vo.setChapterName(cataMap.getOrDefault(question.getChapterId(),""));
        vo.setSectionName(cataMap.getOrDefault(question.getSectionId(),""));

        //7.封装vo
        return vo;



    }
    /**
     * 管理端隐藏或显示问题
     */
    @Override
    public void hiddenQuestion(Long id, Boolean hidden) {
        // 1.更新问题
        InteractionQuestion question = new InteractionQuestion();
        question.setId(id);
        question.setHidden(hidden);
        updateById(question);
    }
}
